package com.hyjiacan.h2c

import com.hyjiacan.h2c.commands.CommandManager
import java.sql.SQLException

class Workbench {
    private lateinit var db: H2
    private var interactive = false

    fun startup() {
        Cmd.pl("正在打开数据库 ${Cmd.url} ...")

        if (!open()) {
            return
        }

        Cmd.pl("已打开")
        Cmd.printLine()

        interactive = true

        Cmd.pp()
        val buffer = StringBuilder()
        while (interactive) {
            val line = readlnOrNull()

            if (line == null) {
                Cmd.printLine()
                Cmd.pl("Ctrl-C 退出")
                interactive = false;
                break
            }

            buffer.append(line + "\n")

            if (line == "" || line.endsWith(';')) {
                if (!handleInput(buffer)) {
                    interactive = false
                    break
                }
                Cmd.pp()
            } else {
                Cmd.p("  -> ")
            }
        }

        db.close()
    }

    private fun open(): Boolean {
        for (i in 0 until 3) {
            if (!userInput()) {
                return false
            }

            db = H2(Cmd.url, Cmd.user, Cmd.pswd)
            return try {
                db.open()
                true
            } catch (e: SQLException) {
                Cmd.warn("打开失败:" + e.message)
                if (e.message == "Wrong user name or password") {
                    continue
                }
                false
            }
        }
        return false
    }

    private fun userInput(): Boolean {
        Cmd.p("请输入用户名 >")
        val user = readlnOrNull()

        if (user == null) {
            Cmd.printLine()
            Cmd.pl("Ctrl-C 退出")
            return false
        }
        Cmd.user = user

        Cmd.p("请输入密码 >")
        val pswd = if (System.console() == null) {
            readlnOrNull()
        } else {
            System.console().readPassword()?.joinToString("")
        }

        if (pswd == null) {
            Cmd.printLine()
            Cmd.pl("Ctrl-C 退出")
            return false
        }

        Cmd.pswd = pswd

        return true
    }

    private fun handleInput(buffer: StringBuilder): Boolean {
        val input = buffer.toString().trim().trimEnd(';').trim()
        if (input == "") {
            return true
        }
        buffer.clear()

        val command = CommandManager.match(input) ?: return true

        return command.run(input, db)
    }
}